package com.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.net.ftp.FTPClient;

public class FtpHandler {
	private static final String IP_ADDRESS = "127.0.0.1";
	private static final String USER_NAME = "admin";
	private static final String PASSWORD = "123456";
	private static final int MAX_VALUE = 2147483646;
	private static AtomicInteger cal = new AtomicInteger(0);
	
	public String upload(final String fileName, final String path) throws FtpException {
		FtpCommand ftpCommand = new FtpCommand() {
			public String command(final FTPClient ftpClient, FileInputStream fis, FileOutputStream fos) throws IOException, FileNotFoundException {
				String uploadFileName = getUploadFileName(fileName);
				File srcFile = new File(fileName); 
	            fis = new FileInputStream(srcFile); 
	            ftpClient.changeWorkingDirectory(path);
	            ftpClient.storeFile("2012-05-09_18:15:05.953_1.xlsx", fis);
	            return path + "/" + uploadFileName;
			}
		};
		return ftpTransfer(ftpCommand);
	}
	
	public String download(final String fileName) throws FtpException {
		FtpCommand ftpCommand = new FtpCommand() {
			public String command(final FTPClient ftpClient, FileInputStream fis, FileOutputStream fos) throws IOException, FileNotFoundException {
				String curDir = System.getProperty("user.dir");
				String localFileName = curDir + "/download" + getTailName(fileName);
				fos = new FileOutputStream(localFileName);
	            ftpClient.retrieveFile(fileName, fos);
	            return localFileName;
			}
		};
		return ftpTransfer(ftpCommand);
	}
	
	private String ftpTransfer(final FtpCommand ftpCommand) throws FtpException {
		FTPClient ftpClient = new FTPClient(); 
		FileInputStream fis = null; 
        FileOutputStream fos = null; 
        String fileName = null;

        try { 
            ftpClient.connect(IP_ADDRESS); 
            ftpClient.login(USER_NAME, PASSWORD);  
            
            ftpClient.setBufferSize(1024); 
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");

            fileName = ftpCommand.command(ftpClient, fis, fos); 
        } catch (IOException e) { 
            throw new FtpException("FTP Client error", e); 
        } finally { 
        	try { 
            	if(fos != null) {
            		fos.close();
            	}
            } catch (IOException e) { 
                throw new FtpException("Error when close FTP file", e); 
            }
            try { 
            	if(ftpClient.isConnected()) {
            		ftpClient.logout();
            		ftpClient.disconnect(); 
            	}
            } catch (IOException e) { 
                e.printStackTrace(); 
                throw new FtpException("Error when close FTP connection", e); 
            } 
        } 
        return fileName;
	}
	
	private String getUploadFileName(String fileName) {
		String timestamp = new Timestamp(System.currentTimeMillis()).toString().replaceAll(" ", "_");
		String tailName = getTailName(fileName);
		int incrementNumber = getAtomicInteger();
		StringBuffer sb = new StringBuffer();
		sb.append(timestamp);
		sb.append("_");
		sb.append(incrementNumber);
		sb.append(tailName);
		return sb.toString();
	}
	
	private synchronized int getAtomicInteger() {
		if(cal.get() >= MAX_VALUE) {
			return cal.getAndSet(0);
		}
		return cal.incrementAndGet();
	}
	
	private String getTailName(String fileName) {
		return fileName.substring(fileName.lastIndexOf('.'));
	}
}
interface FtpCommand {
	public String command(final FTPClient ftpClient, FileInputStream fis, FileOutputStream fos) throws IOException, FileNotFoundException;
}
